﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Sausage.Web.Code;
using Sausage.Web.DataModel;
using Sausage.Web.Models;
using Sausage.Common;
using Telerik.Web.Mvc;

namespace Sausage.Web.Domain
{
    public class EmergencyHelper
    {
        public static Emergency GetEmergencyByID(Guid emergencyID)
        {
            using (var context = new SausageEntities())
            {
                return
                    context.Emergency.Include("Organization").Include("Receivers").Include("Attachments").FirstOrDefault(
                        item => item.EmergencyID == emergencyID);
            }
        }

        public static void CreateEmergency(EmergencyListRow data)
        {
            using (SausageEntities context = new SausageEntities())
            {
                var emergencyID = Guid.NewGuid();
                var emergency = new Emergency()
                                    {
                                        EmergencyID = emergencyID,
                                        OrganizationID = Helper.CurrentPrincipal.Organization.OrganizationID,
                                        CreateDate = DateTime.Now,
                                        Creater = Helper.CurrentPrincipal.User.UserName,
                                        Title = data.Title,
                                        PostType = data.PostType,
                                        State = (int) DataStateEnum.Unsubmit,
                                        Content = data.Content,
                                    };

                context.AddToEmergency(emergency);
                
                //set the receiver.
                if (Helper.CurrentPrincipal.IsDistrictOrganization)
                {
                    //send message from the district
                    if (data.PostType == (int)PostTypeEnum.ToPartial) 
                    {
                        //To partial so need to save the reserver.
                        foreach (var item in data.Receivers)
                        {
                            var organization = new Organization()
                                                   {
                                                       OrganizationID = item
                                                   };
                            context.CreateObjectSet<Organization>().Attach(organization);
                            emergency.Receivers.Add(organization);
                        }
                    }
                    //To all do not need to save the reserver.
                }
                else
                {
                    //send it from the partition
                    //the receiver is the district.
                    var organization = new Organization()
                    {
                        OrganizationID = OrganizationHelper.DistrictOrganization
                    };
                    emergency.PostType = (int) PostTypeEnum.ToDistrict;
                    context.CreateObjectSet<Organization>().Attach(organization);
                    emergency.Receivers.Add(organization);
                }
                context.SaveChanges();
                
                //move the attachments.
                if(data.Attachments != null && data.Attachments.Length>0)
                    FileUploadHelper.MoveFileFromTempToEmergencyAttachment(emergencyID, data.Attachments);
            }
        }

        public static GridModel<object> Select(JosnPagingQueryModel query)
        {
            var organization = OrganizationHelper.GetAllowedOrganizationList();
            using (var context = new SausageEntities())
            {
                if (query.SortModel.Length == 0) //default sort.
                    query.SortModel = new JosnQuerySortModel[] { new JosnQuerySortModel() { property = "CreateDate", direction = "DESC" } };

                return
                    QueryEmergency(
                        context.EmergencyReceiverView.Where(
                        item =>
                        ((item.PostType == (int) PostTypeEnum.ToAll) ||
                             (item.PostType == (int)PostTypeEnum.ToPartial && item.ReceiverID.HasValue && organization.Contains(item.ReceiverID.Value)) ||
                          (item.PostType == (int) PostTypeEnum.ToDistrict && organization.Contains(item.OrganizationID))
                            ) && item.State == (int)DataStateEnum.Submitted).Distinct(),
                        query);


            }
        }

        public static GridModel<object> SubmitSelect(JosnPagingQueryModel query)
        {
            var organization = OrganizationHelper.GetAllowedOrganizationList();
            using (var context = new SausageEntities())
            {
                if(query.SortModel.Length == 0) //default sort.
                    query.SortModel = new JosnQuerySortModel[] { new JosnQuerySortModel() { property = "CreateDate", direction = "DESC" } };

                return
                    QueryEmergency(
                        context.EmergencyReceiverView.Where(
                            item =>
                            organization.Contains(item.OrganizationID) &&
                            item.State == (int)MaintainDataStateEnum.Unsubmit).Distinct(),
                        query);
            }
        }

        private static GridModel<object> QueryEmergency(IQueryable<EmergencyReceiverView> source, JosnPagingQueryModel query)
        {
            var result = UIHelper.GetGridModelFromQueryModel<EmergencyReceiverView>(
                source,
                query.page,
                query.limit,
                GetSortDescriptorFromQueryModel(query.SortModel),
                GetSearchFilterFromQueryModel(query.FilterModel));

            var list = result.Data.Select(emergency => new
            {
                emergency.EmergencyID,
                emergency.Title,
                emergency.OrganizationID,
                Organization = emergency.OrganizationName,
                emergency.PostType,
                emergency.State,
                emergency.Creater,
                emergency.CreateDate
            }).ToList();

            return new GridModel<object>()
            {
                Aggregates = result.Aggregates,
                Data = list,
                Total = result.Total
            };
        }

        private static List<IFilterDescriptor> GetSearchFilterFromQueryModel(IEnumerable<JosnQueryFilterModel> filterModels)
        {
            var filterList = new List<IFilterDescriptor>();
            foreach (var item in filterModels)
            {
                if (string.IsNullOrEmpty(item.value))
                    continue;

                if (item.property.EndsWith("ID", StringComparison.InvariantCultureIgnoreCase))
                {
                    var targetID = Guid.Parse(item.value);
                    if (targetID != Guid.Empty)
                        filterList.Add(new FilterDescriptor(item.property, FilterOperator.IsEqualTo, targetID));
                }
                else //other filter.
                    filterList.Add(new FilterDescriptor(item.property, FilterOperator.Contains, item.value));
            }
            return filterList;
        }

        private static List<SortDescriptor> GetSortDescriptorFromQueryModel(IEnumerable<JosnQuerySortModel> sortModels)
        {
            //convert the sort description.
            var sortList = new List<SortDescriptor>();
            foreach (var item in sortModels)
            {
                var descriptor = new SortDescriptor()
                {
                    Member = item.property,
                    SortDirection =
                        item.direction.ToLower() == "desc"
                            ? ListSortDirection.Descending
                            : ListSortDirection.Ascending
                };

                if (descriptor.Member == "Organization")
                    descriptor.Member = "Organization.OrganizationName";

                sortList.Add(descriptor);
            }
            return sortList;
        }

        public static void UpdateEmergency(EmergencyListRow data)
        {
            using (var context = new SausageEntities())
            {
                var emergency = context.Emergency.FirstOrDefault(item => item.EmergencyID == data.EmergencyID);
                if (emergency == null)
                    return;

                emergency.Title = data.Title;
                emergency.Content = data.Content;
                emergency.PostType = data.PostType;

                emergency.Receivers.Clear();
                context.SaveChanges();
            }

            using(var context = new SausageEntities())
            {
                var emergency = context.Emergency.FirstOrDefault(item => item.EmergencyID == data.EmergencyID);
                //set the receiver.
                if (Helper.CurrentPrincipal.IsDistrictOrganization)
                {
                    //send message from the district
                    if (data.PostType == (int)PostTypeEnum.ToPartial)
                    {
                        //To partial so need to save the reserver.
                        foreach (var item in data.Receivers)
                        {
                            var organization = new Organization()
                            {
                                OrganizationID = item
                            };
                            context.CreateObjectSet<Organization>().Attach(organization);
                            emergency.Receivers.Add(organization);
                        }
                    }
                    //To all do not need to save the reserver.
                }
                else
                {
                    //send it from the partition
                    //the receiver is the district.
                    var organization = new Organization()
                    {
                        OrganizationID = OrganizationHelper.DistrictOrganization
                    };

                    context.CreateObjectSet<Organization>().Attach(organization);
                    emergency.Receivers.Add(organization);
                }
                context.SaveChanges();
            }
        }

        public static void DeleteEmergency(EmergencyListRow data)
        {
            using (var context = new SausageEntities())
            {
                var attachments = context.EmergencyAttachment.Where(attachment => attachment.EmergencyID == data.EmergencyID).ToList();
                var sourceFolder = HttpContext.Current.Server.MapPath(Utility.EmergencyFolder);
                foreach (var attachment in attachments)
                {
                    try
                    {
                        string sourcePath = string.Concat(sourceFolder,
                                                          Path.DirectorySeparatorChar, attachment.AttachmentID,
                                                          attachment.FileExtension);
                        if (File.Exists(sourcePath))
                            File.Delete(sourcePath);
                    }
                    catch {/*do nothing*/}
                }
                
                var emergency =
                    context.Emergency.Where(item => item.EmergencyID == data.EmergencyID).FirstOrDefault();

                if(emergency != null)
                {
                    emergency.Receivers.Clear();
                    context.SaveChanges();
                }
            }

            using (var context = new SausageEntities())
            {
                var emergency =
                    context.Emergency.Where(item => item.EmergencyID == data.EmergencyID).FirstOrDefault();

                if(emergency != null)
                {
                    context.DeleteObject(emergency);
                    context.SaveChanges();
                }
            }
        }

        public static EmergencyAttachment GetAttachment(Guid attachmentID)
        {
            using (var context = new SausageEntities())
            {
                return context.EmergencyAttachment.FirstOrDefault(item => item.AttachmentID == attachmentID);
            }
        }

        public static List<EmergencyAttachment> GetEmergencyAttachment(Guid emergencyID)
        {
            using (var context = new SausageEntities())
            {
                return context.EmergencyAttachment.Where(item => item.EmergencyID == emergencyID).ToList();
            }
        }

        public static void ExecuteSubmit(Guid[] emergencies)
        {
            if (null != emergencies && emergencies.Length > 0)
            {
                using (var context = new SausageEntities())
                {
                    var list = context.Emergency.Where(item => emergencies.Contains(item.EmergencyID)).ToList();

                    foreach (var entity in list)
                    {
                        entity.State = (int) DataStateEnum.Submitted;
                    }
                    context.SaveChanges();
                }
            }
        }

        public static bool DeleteAttachment(EmergencyAttachmentModel data)
        {
            using (var context = new SausageEntities())
            {
                var target =
                    context.EmergencyAttachment.FirstOrDefault(item => item.AttachmentID == data.AttachmentID);
                if (target == null)
                    return true;

                string filePath = string.Concat(HttpContext.Current.Server.MapPath(Utility.EmergencyFolder),
                                                Path.DirectorySeparatorChar, target.AttachmentID, target.FileExtension);

                try
                {
                    if (File.Exists(filePath))
                        File.Delete(filePath);

                    context.DeleteObject(target);
                    context.SaveChanges();
                }
                catch
                {
                    return false;
                }
            }
            return true;
        }
    }
}
